{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "431469a8-b15b-4a5d-8559-f8561ccb75f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import warnings\n",
    "\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a53fde7e-f24f-4cb0-9962-9ed075790628",
   "metadata": {},
   "outputs": [],
   "source": [
    "from gs_quant.session import GsSession\n",
    "\n",
    "GsSession.use()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a9bc9fb-3914-49fc-b3cf-4e59d22fd8a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "from gs_quant.instrument import FXOption\n",
    "from gs_quant.backtests.strategy import Strategy\n",
    "from gs_quant.backtests.triggers import *\n",
    "from gs_quant.backtests.actions import *\n",
    "from gs_quant.backtests.equity_vol_engine import *\n",
    "from gs_quant.backtests.generic_engine import GenericEngine\n",
    "from datetime import date"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a6175aa-bd47-4cd3-bead-dcebe4f5ea8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialize session\n",
    "from gs_quant.session import GsSession\n",
    "\n",
    "GsSession.use(client_id=None, client_secret=None, scopes=('run_analytics',))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3911f5d4-3a4b-4fca-9404-315dfa03aea9",
   "metadata": {},
   "source": [
    "#### If we have a periodic trigger which triggers every 1w and has an add trade action which has a trade duration of 1w sometimes you can end up with a situation where you have 2 trades or 0 trades.  \n",
    "#### This is because the schedule of 1w dates for the trigger will derive a schedule of 1w dates and then adjust each date for holidays.  Where as if you take a specific date and add a week this will not take note of the holiday and therefore may give a different date."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e2c6435-b2a0-4824-ae5c-4d4ef0f42ee4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define backtest dates\n",
    "start_date = date(2024, 3, 24)\n",
    "end_date = date(2024, 5, 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2f30447d-103c-4792-adec-8c7f2516b617",
   "metadata": {},
   "outputs": [],
   "source": [
    "call = FXOption(pair='EURUSD', expiration_date='3m', option_type='Call', name='call')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f62f44c9-d432-4212-9313-966c9e7b52ec",
   "metadata": {},
   "source": [
    "### Entering a position weekly"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "adb4fc9d-1c23-40a6-b109-3ca8425ad623",
   "metadata": {},
   "outputs": [],
   "source": [
    "# To demonstrate create add trade action with a duration of 1w on a periodic trigger of 1w across a holiday\n",
    "hol_cal = (dt.date(2024, 3, 29), dt.date(2024, 4, 1))\n",
    "trade_action = AddTradeAction(priceables=call, trade_duration='1w', name='weekly_duration', holiday_calendar=hol_cal)\n",
    "trade_trigger = PeriodicTrigger(\n",
    "    trigger_requirements=PeriodicTriggerRequirements(\n",
    "        start_date=start_date, end_date=end_date, frequency='1w', calendar=hol_cal\n",
    "    ),\n",
    "    actions=trade_action,\n",
    ")\n",
    "\n",
    "strategy = Strategy(None, trade_trigger)\n",
    "\n",
    "# Run backtest daily\n",
    "GE = GenericEngine()\n",
    "backtest = GE.run_backtest(strategy, start=start_date, end=end_date, frequency='1b', show_progress=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9c126b67-aecf-4493-9ac6-397b984852ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "# View backtest trade ledger\n",
    "backtest.trade_ledger()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2fd8f5f6-7521-4182-a0ec-193f39553860",
   "metadata": {},
   "source": [
    "#### note that the second trade closes on the 4th April but the third trade opens on the 5th."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7248340c-13b8-4c98-b837-1a5e4a12b88f",
   "metadata": {},
   "source": [
    "In order to fix this we can set the trade duration to <span style=\"color:blue\">\"next schedule\"</span>.\n",
    "This will have the effect of forcing the close date to line up with the open date of the following trade.\n",
    "\n",
    "This should only be used if you want the trade duration of the trade and the frequency of the trigger to line up \n",
    "and the frequency is not daily.  Thereby chaining (or rolling) the positions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1d2cf05-0622-4899-af32-be9dc0fad840",
   "metadata": {},
   "outputs": [],
   "source": [
    "hol_cal = (dt.date(2024, 3, 29), dt.date(2024, 4, 1))\n",
    "trade_action = AddTradeAction(\n",
    "    priceables=call, trade_duration='next schedule', name='weekly_duration', holiday_calendar=hol_cal\n",
    ")\n",
    "trade_trigger = PeriodicTrigger(\n",
    "    trigger_requirements=PeriodicTriggerRequirements(\n",
    "        start_date=start_date, end_date=end_date, frequency='1w', calendar=hol_cal\n",
    "    ),\n",
    "    actions=trade_action,\n",
    ")\n",
    "\n",
    "strategy = Strategy(None, trade_trigger)\n",
    "\n",
    "# Run backtest daily\n",
    "GE = GenericEngine()\n",
    "backtest = GE.run_backtest(strategy, start=start_date, end=end_date, frequency='1b', show_progress=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13b2bdc3-c710-4cd3-a020-23e8f1351151",
   "metadata": {},
   "outputs": [],
   "source": [
    "# View backtest trade ledger\n",
    "backtest.trade_ledger()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca734a86-f37f-497e-bd96-34044a95d70a",
   "metadata": {},
   "source": [
    "#### now note that all the trades start and end dates line up"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "294b7063-3aff-4322-a400-070bc0b1ce35",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
